﻿using Ongoal.Quotation.Common;
using Ongoal.Quotation.Cap;
using Ongoal.Quotation.Common;
using Ongoal.Quotation.Service;
using Ongoal.Quotation.Service.Common;
using Ongoal.Quotation.Service.Interface;
using Ongoal.Quotation.Service.Model;
using Ongoal.Quotation.Service.Model.basemodel;
using Ongoal.Quotation.Service.Model.Sys;
using Ongoal.Quotation.Service.ViewModel;
using SqlSugar;

namespace Ongoal.Quotation.Service
{
    public class CodeService : ServiceBase, ICodeService
    {
        private IMessagePublisher _messagePublisher;
        public CodeService(IMessagePublisher messagePublisher)
        {
            _messagePublisher = messagePublisher;
        }

        public Dictionary<string, List<dynamic>> GetCode(string codeStr)
        {
            //Console.WriteLine(this.Db);
            var result = new Dictionary<string, List<dynamic>>();
            if (!string.IsNullOrEmpty(codeStr))
            {
                var codeList = codeStr.Split(',');
                var dbclient = this.Db!.GetDbContext(string.Empty);
                foreach (var code in codeList)
                {
                    var redisKey = $"SYS:CODE:{code.ToUpper()}";
                    if (this.Redis!.Exists(redisKey))
                    {
                        //缓存里面有，则直接读取缓存
                        result.Add(code, this.Redis!.Get<List<dynamic>>(redisKey));
                    }
                    else
                    {
                        //缓存里面没有，则读取数据库并存缓存
                        var tableInfo = dbclient.Queryable<T_CodeTable>().Where(t => t.Code == code).First();
                        if (tableInfo != null)
                        {
                            var itemList = dbclient.Queryable<T_CodeItem>().Where(t => t.TableID == tableInfo.ID && t.Deleted == 0).OrderBy(t => t.CreateTime, OrderByType.Desc).ToList();
                            List<dynamic> valueList;
                            if (tableInfo.CodeType == (int)ETableType.Tree)
                            {
                                //如果是树形表，则将记录处理成树形
                                var rootlist = itemList.Where(t => t.ParentID == 0).Select<T_CodeItem, dynamic>(t => new viewroot
                                {
                                    label = t.CodeText,
                                    value = t.CodeValue,
                                    children = new List<viewroot>(),
                                    code = t.Code,
                                    ID = t.ID,
                                }).ToList();
                                foreach (var item in rootlist)
                                {
                                    BuildTree(item, itemList);
                                }
                                valueList = rootlist.ToList();
                            }
                            else
                            {
                                valueList = itemList.Select<T_CodeItem, dynamic>(t => new
                                {
                                    label = t.CodeText,
                                    value = t.CodeValue,
                                    code = t.Code
                                }).ToList();
                            }

                            this.Redis!.Set(redisKey, valueList);
                            result.Add(code, valueList);
                        }
                    }
                }
            }
            return result;
        }

        private void BuildTree(viewroot root, List<T_CodeItem> childrenList)
        {
            List<viewroot> tempList = childrenList.Where(t => t.ParentID == root.ID).Select(t => new viewroot
            {
                label = t.CodeText,
                value = t.CodeValue,
                code = t.Code,
                ID = t.ID
            }).ToList();
            if (tempList.Count > 0)
            {
                root.children = tempList.Select(t => new viewroot
                {
                    label = t.label,
                    value = t.value,
                    code = t.code,
                    ID = t.ID,
                }).ToList();
                foreach (var child in root.children)
                {
                    BuildTree(child, childrenList);
                }
            }
            else
            {
                root.children = null;
            }
        }


        /// <summary>
        /// 添加代码项
        /// </summary>
        /// <param name="model"></param>
        /// <returns></returns>
        public void AddCodeItem(V_CodeItem model)
        {
            var t = this.Db.GetDbContext(string.Empty).Queryable<T_CodeItem>().Where(t => t.TableID == model.TableID && (t.CodeText == model.CodeText || t.Code == model.Code)).Any();
            if (t)
            {
                throw new Exception("代码项与编码不能重复");
            }
            T_CodeItem entitymodel = ExpressionMapper<V_CodeItem, T_CodeItem>.Map(model);
            var redisKey = $"SYS:CODE:{model.TableCode.ToUpper()}";
            if (this.Redis!.Exists(redisKey))
            {
                this.Redis.Del("Public", redisKey);
            }
            //保存并且推送数据
            this.InsertAndPublish<T_CodeItem>(entitymodel, _messagePublisher, MessageConstant.CodeItem);

        }

        /// <summary>
        /// 编辑代码项
        /// </summary>
        /// <param name="model"></param>
        /// <returns></returns>
        public void UpdateCodeItem(V_CodeItem model)
        {
            var t = this.Db.GetDbContext(string.Empty).Queryable<T_CodeItem>().Where(t => t.TableID == model.TableID && (t.CodeValue == model.CodeValue || t.Code==model.Code ) && t.ID != model.ID).Any();
            if (t)
            {
                throw new Exception("代码项与编码不能重复");
            }
            T_CodeItem entitymodel = ExpressionMapper<V_CodeItem, T_CodeItem>.Map(model);
            var redisKey = $"SYS:CODE:{model.TableCode.ToUpper()}";
            if (this.Redis!.Exists(redisKey))
            {
                this.Redis.Del("Public", redisKey);
            }
            //保存并且推送数据
            this.UpdateAndPublish<T_CodeItem>(entitymodel, _messagePublisher, MessageConstant.CodeItem);
        }

        /// <summary>
        /// 删除代码项
        /// </summary>
        /// <param name="model"></param>
        public void DeleteCodeItem(V_CodeItem model)
        {

            var redisKey = $"SYS:CODE:{model.TableCode.ToUpper()}";
            if (this.Redis!.Exists(redisKey))
            {
                this.Redis.Del("Public", redisKey);
            }
            this.DeleteAndPublish<T_CodeItem>(new int[1] { model.ID }, _messagePublisher, MessageConstant.DeleteCodeItem);
        }




        #region 外键
        /// <summary>
        /// 获取外键信息
        /// </summary>
        /// <param name="ModelList">外键参数集合</param>
        public Dictionary<string, List<dynamic>> GetCode_Foreign(List<T_Sys_Interfacesettings> ModelList)
        {
            var result = new Dictionary<string, List<dynamic>>();
            var dbclient = this.Db!.GetDbContext(string.Empty);
            foreach (var item in ModelList)
            {
                List<dynamic> valueList = new List<dynamic>();
                var TableInfo = dbclient.Queryable<T_TableInfo>().Where(t => t.ID == item.ForeignTableID).First();//获取表信息
                if (TableInfo != null)
                {
                    var Filed = dbclient.Queryable<R_Table_Filed_Reference>().Where(t => t.ID == item.ForeignFiledID).First();//获取值字段
                    var LableFiled = dbclient.Queryable<R_Table_Filed_Reference>().Where(t => t.ID == item.ForeignLableFiled).First();//获取显示字段
                    if (Filed != null && LableFiled != null)
                    {
                        var MeasuredUnit = "";
                        //物料-特殊处理
                        if (item.ForeignTableID == 81)
                        {
                            MeasuredUnit = ",UnitMeasure as code ";
                        }
                        else if (item.ForeignTableID == 85)
                        {
                            MeasuredUnit = ",DsData as code ";
                        }
                        //原生SQL用匿名对象 sql 查询
                        var sql = string.Format(" select ID,{0} as value,{1} as label{2} from {3} ", Filed.FiledCode, LableFiled.FiledCode, MeasuredUnit, TableInfo.TableCode);
                        //如果是树形表，则将记录处理成树形
                        if (TableInfo.Islevel == 1)//树形
                        {
                            //获取主父节点信息
                            var rootlist = dbclient.Ado.SqlQuery<viewroot>(sql + " where ParentID=0 ").Select<viewroot, dynamic>(t => new viewroot
                            {
                                label = t.label,
                                value = t.value,
                                children = new List<viewroot>(),
                                ID = t.ID,
                            }).ToList();
                            foreach (var items in rootlist)
                            {
                                BuildCode_ForeignTree(items, sql, dbclient);//设置子节点
                            }
                            valueList = rootlist.ToList();
                        }
                        else
                        {
                            valueList = dbclient.Ado.SqlQuery<dynamic>(sql);
                        }
                    }
                    result.Add(item.ID.ToString(), valueList);
                }
            }
            return result;
        }

        /// <summary>
        /// 树形外键子节点
        /// </summary>
        /// <param name="root"></param>
        /// <param name="sql"></param>
        /// <param name="dbclient"></param>
        private void BuildCode_ForeignTree(viewroot root, string sql, SqlSugarClient dbclient)
        {
            var itemsql = string.Format(sql + " where ParentID={0}", root.ID);//获取子节点sql
            var itemList = dbclient.Ado.SqlQuery<viewroot>(itemsql).ToList();//获取子节点信息
            if (itemList.Count > 0)
            {
                foreach (var child in itemList)
                {
                    BuildCode_ForeignTree(child, sql, dbclient);
                }
                root.children = itemList.Select(t => new viewroot
                {
                    label = t.label,
                    value = t.value,
                    children = t.children,
                    ID = t.ID,
                }).ToList();
            }
            else
            {
                root.children = null;
            }
        }
        #endregion

    }

    public class viewroot
    {
        public int ID { get; set; }
        public string label { get; set; }
        public int value { get; set; }
        public string code { get; set; }
        public List<viewroot> children { get; set; }
    }


}
